home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / pibterm / pibt41s2.arc / PIBASYN3.MOD < prev    next >
Encoding:
Text File  |  1988-02-11  |  46.8 KB  |  909 lines

  1. (*----------------------------------------------------------------------*)
  2. (* Async_Find_Delay  --- Finds delay loop value for 1 millesecond delay *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Async_Find_Delay( VAR One_MS_Delay : INTEGER );
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*      Procedure: Async_Find_Delay                                     *)
  10. (*                                                                      *)
  11. (*      Purpose:   Finds loop count value to effect 1 ms delay          *)
  12. (*                                                                      *)
  13. (*      Calling Sequence:                                               *)
  14. (*                                                                      *)
  15. (*         Async_Find_Delay( VAR One_MS_Delay : INTEGER );              *)
  16. (*                                                                      *)
  17. (*            One_MS_Delay --- Resulting loop count for 1 ms delay      *)
  18. (*                                                                      *)
  19. (*      Using result:                                                   *)
  20. (*                                                                      *)
  21. (*            Use loop of form:                                         *)
  22. (*                                                                      *)
  23. (*                      MOV    CX,[>One_MS_Delay]                       *)
  24. (*               Delay: LOOP   Delay                                    *)
  25. (*                                                                      *)
  26. (*            to delay for 1 ms.                                        *)
  27. (*                                                                      *)
  28. (*      Remarks:                                                        *)
  29. (*                                                                      *)
  30. (*         This routine watches over the CPU elapsed timer value for    *)
  31. (*         just one timer interval (55 milleseconds).  During that time *)
  32. (*         we run a tight loop and accumulate the ticks.  The result    *)
  33. (*         is the number of ticks required for a 55 ms delay.  The      *)
  34. (*         ticks for a 1 ms delay = ( ticks for 55 ms ) / 55.           *)
  35. (*                                                                      *)
  36. (*         To avoid overflow problems on fast machines, and to ease the *)
  37. (*         worry about storing results at the second timer tick, we     *)
  38. (*         break up the single long tight loop into a series of short   *)
  39. (*         loops inside an outer loop.  We check if the timer has       *)
  40. (*         expired at the end of each inner short loop.  Then the       *)
  41. (*         time for the 55 ms delay is:                                 *)
  42. (*                                                                      *)
  43. (*            Ticks_for_55 := Inner_Ticks * Outer_Ticks;                *)
  44. (*                                                                      *)
  45. (*         and the corresponding 1 ms delay is:                         *)
  46. (*                                                                      *)
  47. (*            Ticks_For_1  := Ticks_For_55 DIV 55;                      *)
  48. (*                                                                      *)
  49. (*         To simplify things, we choose the inner tick value to be     *)
  50. (*         2 x 55 = 110.  Then:                                         *)
  51. (*                                                                      *)
  52. (*            Ticks_For_1  := ( 110 * Outer_Ticks ) / 55;  ==>          *)
  53. (*            Ticks_For_1  := 2 * Outer_Ticks;                          *)
  54. (*                                                                      *)
  55. (*         The CPU timer is located in four bytes at $0000:$46C.        *)
  56. (*         Interrupt $1A also returns these bytes, but using the        *)
  57. (*         interrupt results in an inaccurate loop count value.         *)
  58. (*                                                                      *)
  59. (*         Thanks to Brian Foley and Kim Kokonnen for help with this    *)
  60. (*         problem.                                                     *)
  61. (*                                                                      *)
  62. (*----------------------------------------------------------------------*)
  63.  
  64. (* STRUCTURED *) CONST
  65.    Hi_Timer         : INTEGER = 0  (* Saves high portion of timer        *);
  66.    Lo_Timer         : INTEGER = 0  (* Saves low portion of timer         *);
  67.    OutCount         : INTEGER = 0  (* Accumulates outer loop counts      *);
  68.  
  69. BEGIN (* Async_Find_Delay *)
  70.  
  71. INLINE(
  72.                              {;}
  73.   $31/$C0/                   {          XOR    AX,AX                 ;Clear AX to zero}
  74.   $8E/$C0/                   {          MOV    ES,AX                 ;Allow low-memory access}
  75.                              {;}
  76.   $C7/$06/>OUTCOUNT/$00/$00/ {          MOV    WORD [>OutCount],0    ;Clear outer loop counter}
  77.                              {;}
  78.   $FA/                       {          CLI                          ;No interrupts while reading}
  79.   $26/$8B/$0E/>$46E/         {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  80.   $26/$8B/$16/>$46C/         {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  81.   $FB/                       {          STI                          ;Interrupts back on}
  82.                              {;}
  83.   $89/$0E/>HI_TIMER/         {          MOV    [>Hi_Timer],CX        ;Save hi part of timer}
  84.   $89/$16/>LO_TIMER/         {          MOV    [>Lo_Timer],DX        ;Save low part of timer}
  85.                              {;}
  86.   $FA/                       {Loop1:    CLI                          ;No interrupts while reading}
  87.                              {;}
  88.   $26/$8B/$0E/>$46E/         {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  89.   $26/$8B/$16/>$46C/         {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  90.                              {;}
  91.   $FB/                       {          STI                          ;Interrupts back on}
  92.                              {;}
  93.   $89/$C8/                   {          MOV    AX,CX                 ;Save CX and DX for later}
  94.   $89/$D3/                   {          MOV    BX,DX}
  95.                              {;}
  96.   $2B/$06/>HI_TIMER/         {          SUB    AX,[>Hi_Timer]        ;Subtract low order part}
  97.   $1B/$1E/>LO_TIMER/         {          SBB    BX,[>Lo_Timer]        ;Subtract high order part}
  98.                              {;}
  99.   $74/$E6/                   {          JE     Loop1                 ;Continue until non-0 tick difference}
  100.                              {;}
  101.   $89/$0E/>HI_TIMER/         {          MOV    [>Hi_Timer],CX        ;Save hi part}
  102.   $89/$16/>LO_TIMER/         {          MOV    [>Lo_Timer],DX        ;Save low part}
  103.                              {;}
  104.   $B9/$6E/$00/               {Loop2:    MOV    CX,110                ;Run short delay loop.}
  105.   $E2/$FE/                   {Delay:    LOOP   Delay}
  106.                              {;}
  107.   $FA/                       {          CLI                          ;No interrupts while reading}
  108.                              {;}
  109.   $26/$8B/$0E/>$46E/         {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  110.   $26/$8B/$16/>$46C/         {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  111.                              {;}
  112.   $FB/                       {          STI                          ;Interrupts back on}
  113.                              {;}
  114.   $FF/$06/>OUTCOUNT/         {          INC    WORD [>OutCount]      ;Increment outer loop count}
  115.                              {;}
  116.   $2B/$0E/>HI_TIMER/         {          SUB    CX,[>Hi_Timer]        ;Subtract low order part}
  117.   $1B/$16/>LO_TIMER/         {          SBB    DX,[>Lo_Timer]        ;Subtract high order part}
  118.                              {;}
  119.   $74/$E1/                   {          JE     Loop2                 ;Keep going if next tick not found}
  120.                              {;}
  121.   $A1/>OUTCOUNT/             {          MOV    AX,[>OutCount]        ;Pick up outer loop counter}
  122.   $D1/$E0/                   {          SHL    AX,1                  ;* 2 = ticks for 1 ms delay}
  123.                              {;}
  124.   $C4/$BE/>ONE_MS_DELAY/     {          LES    DI,[BP+>One_MS_Delay] ;Get address of result}
  125.   $26/$89/$05);              {      ES: MOV    [DI],AX               ;Store result}
  126.  
  127. END   (* Async_Find_Delay *);
  128.  
  129. (*----------------------------------------------------------------------*)
  130. (*               Async_Init --- Initialize Asynchronous Variables       *)
  131. (*----------------------------------------------------------------------*)
  132.  
  133. PROCEDURE Async_Init( Async_Buffer_Max  : INTEGER;
  134.                       Async_OBuffer_Max : INTEGER;
  135.                       Async_High_Lev1   : INTEGER;
  136.                       Async_High_Lev2   : INTEGER;
  137.                       Async_Low_Lev     : INTEGER );
  138.  
  139. (*----------------------------------------------------------------------*)
  140. (*                                                                      *)
  141. (*     Procedure:  Async_Init                                           *)
  142. (*                                                                      *)
  143. (*     Purpose:    Initializes variables                                *)
  144. (*                                                                      *)
  145. (*     Calling Sequence:                                                *)
  146. (*                                                                      *)
  147. (*         Async_Init( Async_Buffer_Max  : INTEGER;                     *)
  148. (*                     Async_OBuffer_Max : INTEGER;                     *)
  149. (*                     Async_High_Lev1   : INTEGER;                     *)
  150. (*                     Async_High_Lev2   : INTEGER;                     *)
  151. (*                     Async_Low_Lev     : INTEGER );                   *)
  152. (*                                                                      *)
  153. (*     Calls:  Async_Find_Delay                                         *)
  154. (*             TurnOffTimeSharing                                       *)
  155. (*             TurnOnTimeSharing                                        *)
  156. (*                                                                      *)
  157. (*----------------------------------------------------------------------*)
  158.  
  159. VAR
  160.    I: INTEGER;
  161.  
  162. (*----------------------------------------------------------------------*)
  163.  
  164. BEGIN   (* Async_Init *)
  165.                                    (* No port open yet.                 *)
  166.    Async_Open_Flag        := FALSE;
  167.  
  168.                                    (* No XON/XOFF handling yet.         *)
  169.    Async_XOFF_Sent        := FALSE;
  170.    Async_XOFF_Received    := FALSE;
  171.    Async_XOFF_Rec_Display := FALSE;
  172.    Async_XON_Rec_Display  := FALSE;
  173.    Async_Send_XOFF        := FALSE;
  174.  
  175.                                    (* Sender not enabled.               *)
  176.    Async_Sender_On        := FALSE;
  177.  
  178.                                    (* Set up empty receive buffer       *)
  179.    Async_Buffer_Overflow  := FALSE;
  180.    Async_Buffer_Used      := 0;
  181.    Async_MaxBufferUsed    := 0;
  182.    Async_Buffer_Head      := 0;
  183.    Async_Buffer_Tail      := 0;
  184.                                    (* Set up empty send buffer.         *)
  185.    Async_OBuffer_Overflow := FALSE;
  186.    Async_OBuffer_Used     := 0;
  187.    Async_MaxOBufferUsed   := 0;
  188.    Async_OBuffer_Head     := 0;
  189.    Async_OBuffer_Tail     := 0;
  190.                                    (* Set default wait time for output   *)
  191.                                    (* buffer to drain when it fills up.  *)
  192.    Async_Output_Delay     := 500;
  193.  
  194.                                    (* No modem or line errors yet.       *)
  195.    Async_Line_Status      := 0;
  196.    Async_Modem_Status     := 0;
  197.    Async_Line_Error_Flags := 0;
  198.  
  199.                                    (* Get buffer sizes *)
  200.  
  201.    IF ( Async_Buffer_Max > 0 ) THEN
  202.       Async_Buffer_Size := Async_Buffer_Max  - 1
  203.    ELSE
  204.       Async_Buffer_Size := 4095;
  205.  
  206.    IF ( Async_OBuffer_Max > 0 ) THEN
  207.       Async_OBuffer_Size := Async_OBuffer_Max - 1
  208.    ELSE
  209.       Async_OBuffer_Size := 1131;
  210.  
  211.                                    (* Get receive buffer overflow *)
  212.                                    (* check-points.               *)
  213.    IF ( Async_Low_Lev > 0 ) THEN
  214.       Async_Buffer_Low := Async_Low_Lev
  215.    ELSE
  216.       Async_Buffer_Low := Async_Buffer_Size DIV 4;
  217.  
  218.    IF ( Async_High_Lev1 > 0 ) THEN
  219.       Async_Buffer_High := Async_High_Lev1
  220.    ELSE
  221.       Async_Buffer_High := ( Async_Buffer_Size DIV 4 ) * 3;
  222.  
  223.    IF ( Async_High_Lev2 > 0 ) THEN
  224.       Async_Buffer_High_2 := Async_High_Lev2
  225.    ELSE
  226.       Async_Buffer_High_2 := ( Async_Buffer_Size DIV 10 ) * 9;
  227.  
  228.                                    (* Allocate buffers *)
  229.  
  230.    GETMEM( Async_Buffer_Ptr  , Async_Buffer_Size  + 1 );
  231.    GETMEM( Async_OBuffer_Ptr , Async_OBuffer_Size + 1 );
  232.  
  233.                                    (* No UART addresses defined yet *)
  234.    Async_Uart_IER         := 0;
  235.    Async_Uart_IIR         := 0;
  236.    Async_Uart_MSR         := 0;
  237.    Async_Uart_LSR         := 0;
  238.    Async_Uart_MCR         := 0;
  239.                                    (* Set default port addresses *)
  240.                                    (* and default IRQ lines      *)
  241.    FOR I := 1 TO MaxComPorts DO
  242.       BEGIN
  243.          Com_Base[I]  := Default_Com_Base [I];
  244.          Com_Irq [I]  := Default_Com_Irq  [I];
  245.          Com_Int [I]  := Default_Com_Int  [I];
  246.       END;
  247.                                    (* Get the delay loop value for 1 ms *)
  248.                                    (* delay loops.                      *)
  249.  
  250. (* ---- You should turn off time sharing if running under a multitasker *)
  251. (* ---- to get an accurate delay loop value.  If MTASK is $DEFINEd,     *)
  252. (* ---- then the calls to the PibMDos routines for interfacing with     *)
  253. (* ---- multitaskers will be generated.                                 *)
  254.  
  255. {$IFDEF MTASK}
  256.    IF TimeSharingActive THEN
  257.       TurnOffTimeSharing;
  258. {$ENDIF}
  259.  
  260.    Async_Find_Delay( Async_OneMSDelay );
  261.  
  262. {$IFDEF MTASK}
  263.    IF TimeSharingActive THEN
  264.       TurnOnTimeSharing;
  265. {$ENDIF}
  266.  
  267. END     (* Async_Init *);
  268.  
  269. (*----------------------------------------------------------------------*)
  270. (*      Async_Carrier_Detect --- Check for modem carrier detect         *)
  271. (*----------------------------------------------------------------------*)
  272.  
  273. FUNCTION Async_Carrier_Detect : BOOLEAN;
  274.  
  275. (*----------------------------------------------------------------------*)
  276. (*                                                                      *)
  277. (*     Function:   Async_Carrier_Detect                                 *)
  278. (*                                                                      *)
  279. (*     Purpose:    Looks for modem carrier detect                       *)
  280. (*                                                                      *)
  281. (*     Calling Sequence:                                                *)
  282. (*                                                                      *)
  283. (*        Flag := Async_Carrier_Detect : BOOLEAN;                       *)
  284. (*                                                                      *)
  285. (*           Flag is set TRUE if carrier detected, else FALSE.          *)
  286. (*                                                                      *)
  287. (*     Calls:  None                                                     *)
  288. (*                                                                      *)
  289. (*----------------------------------------------------------------------*)
  290.  
  291. BEGIN (* Async_Carrier_Detect *)
  292.  
  293.    Async_Carrier_Detect := ODD( Port[ UART_MSR + Async_Base ] SHR 7 ) OR
  294.                            Async_Hard_Wired_On;
  295.  
  296. END   (* Async_Carrier_Detect *);
  297.  
  298. (*----------------------------------------------------------------------*)
  299. (*      Async_Carrier_Drop --- Check for modem carrier drop/timeout     *)
  300. (*----------------------------------------------------------------------*)
  301.  
  302. FUNCTION Async_Carrier_Drop : BOOLEAN;
  303.  
  304. (*----------------------------------------------------------------------*)
  305. (*                                                                      *)
  306. (*     Function:   Async_Carrier_Drop                                   *)
  307. (*                                                                      *)
  308. (*     Purpose:    Looks for modem carrier drop/timeout                 *)
  309. (*                                                                      *)
  310. (*     Calling Sequence:                                                *)
  311. (*                                                                      *)
  312. (*        Flag := Async_Carrier_Drop : BOOLEAN;                         *)
  313. (*                                                                      *)
  314. (*           Flag is set TRUE if carrier dropped, else FALSE.           *)
  315. (*                                                                      *)
  316. (*     Calls:  None                                                     *)
  317. (*                                                                      *)
  318. (*----------------------------------------------------------------------*)
  319.  
  320. BEGIN (* Async_Carrier_Drop *)
  321.  
  322.    Async_Carrier_Drop := NOT ( ODD( Port[ UART_MSR + Async_Base ] SHR 7 ) OR
  323.                                Async_Hard_Wired_On );
  324.  
  325. END   (* Async_Carrier_Drop *);
  326.  
  327. (*----------------------------------------------------------------------*)
  328. (*      Async_Term_Ready --- Set terminal ready status                  *)
  329. (*----------------------------------------------------------------------*)
  330.  
  331. PROCEDURE Async_Term_Ready( Ready_Status : BOOLEAN );
  332.  
  333. (*----------------------------------------------------------------------*)
  334. (*                                                                      *)
  335. (*     Procedure:  Async_Term_Ready                                     *)
  336. (*                                                                      *)
  337. (*     Purpose:    Sets terminal ready status                           *)
  338. (*                                                                      *)
  339. (*     Calling Sequence:                                                *)
  340. (*                                                                      *)
  341. (*        Async_Term_Ready( Ready_Status : BOOLEAN );                   *)
  342. (*                                                                      *)
  343. (*           Ready_Status --- Set TRUE to set terminal ready on,        *)
  344. (*                            Set FALSE to set terminal ready off.      *)
  345. (*                                                                      *)
  346. (*     Calls:  None                                                     *)
  347. (*                                                                      *)
  348. (*----------------------------------------------------------------------*)
  349.  
  350. VAR
  351.    Mcr_Value: BYTE;
  352.  
  353. BEGIN (* Async_Term_Ready *)
  354.  
  355.    Mcr_Value := Port[ UART_MCR + Async_Base ];
  356.  
  357.    IF ODD( Mcr_Value ) THEN Mcr_Value := Mcr_Value - 1;
  358.  
  359.    IF Ready_Status THEN Mcr_Value := Mcr_Value + 1;
  360.  
  361.    Port[ UART_MCR + Async_Base ] := Mcr_Value;
  362.  
  363.    Async_Clear_Errors;
  364.  
  365. END   (* Async_Term_Ready *);
  366.  
  367. (*----------------------------------------------------------------------*)
  368. (*          Async_Buffer_Check --- Check if character in buffer         *)
  369. (*----------------------------------------------------------------------*)
  370.  
  371. FUNCTION Async_Buffer_Check : BOOLEAN;
  372.  
  373. (*----------------------------------------------------------------------*)
  374. (*                                                                      *)
  375. (*     Function:   Async_Buffer_Check                                   *)
  376. (*                                                                      *)
  377. (*     Purpose:    Check if character in buffer                         *)
  378. (*                                                                      *)
  379. (*     Calling Sequence:                                                *)
  380. (*                                                                      *)
  381. (*        Flag := Async_Buffer_Check : BOOLEAN;                         *)
  382. (*                                                                      *)
  383. (*           Flag returned TRUE if character received in buffer,        *)
  384. (*           Flag returned FALSE if no character received.              *)
  385. (*                                                                      *)
  386. (*     Calls:  None                                                     *)
  387. (*                                                                      *)
  388. (*     Remarks:                                                         *)
  389. (*                                                                      *)
  390. (*       This routine only checks if a character has been received      *)
  391. (*       and thus can be read; it does NOT return the character.        *)
  392. (*       Use Async_Receive to read the character.                       *)
  393. (*                                                                      *)
  394. (*----------------------------------------------------------------------*)
  395.  
  396. BEGIN   (* Async_Buffer_Check *)
  397.  
  398.    Async_Buffer_Check := ( Async_Buffer_Head <> Async_Buffer_Tail );
  399.  
  400. END     (* Async_Buffer_Check *);
  401.  
  402. (*----------------------------------------------------------------------*)
  403. (*          Async_Line_Error --- Check if line status error occurred    *)
  404. (*----------------------------------------------------------------------*)
  405.  
  406. FUNCTION Async_Line_Error( VAR Error_Flags: BYTE ) : BOOLEAN;
  407.  
  408. (*----------------------------------------------------------------------*)
  409. (*                                                                      *)
  410. (*     Function:   Async_Line_Error                                     *)
  411. (*                                                                      *)
  412. (*     Purpose:    Check if line status error occurred                  *)
  413. (*                                                                      *)
  414. (*     Calling Sequence:                                                *)
  415. (*                                                                      *)
  416. (*        Flag := Async_Line_Error(VAR Error_Flags: BYTE): BOOLEAN;   *)
  417. (*                                                                      *)
  418. (*           Error_Flags --- Current error flags                        *)
  419. (*                                                                      *)
  420. (*           Flag returned TRUE if line status error occurred,          *)
  421. (*           Flag returned FALSE if no error.                           *)
  422. (*                                                                      *)
  423. (*     Calls:  None                                                     *)
  424. (*                                                                      *)
  425. (*     Remarks:                                                         *)
  426. (*                                                                      *)
  427. (*        The line status error flag is cleared here.                   *)
  428. (*                                                                      *)
  429. (*----------------------------------------------------------------------*)
  430.  
  431. BEGIN   (* Async_Line_Error *)
  432.  
  433.    Async_Line_Error       := ( Async_Line_Error_Flags <> 0 );
  434.    Error_Flags            := Async_Line_Error_Flags;
  435.    Async_Line_Error_Flags := 0;
  436.  
  437. END     (* Async_Line_Error  *);
  438.  
  439. (*----------------------------------------------------------------------*)
  440. (*            Async_Ring_Detect --- Check for phone ringing             *)
  441. (*----------------------------------------------------------------------*)
  442.  
  443. FUNCTION Async_Ring_Detect : BOOLEAN;
  444.  
  445. (*----------------------------------------------------------------------*)
  446. (*                                                                      *)
  447. (*     Function:   Async_Ring_Detect                                    *)
  448. (*                                                                      *)
  449. (*     Purpose:    Looks for phone ringing                              *)
  450. (*                                                                      *)
  451. (*     Calling Sequence:                                                *)
  452. (*                                                                      *)
  453. (*        Flag := Async_Ring_Detect : BOOLEAN;                          *)
  454. (*                                                                      *)
  455. (*           Flag is set TRUE if ringing detected, else FALSE.          *)
  456. (*                                                                      *)
  457. (*     Calls:  None                                                     *)
  458. (*                                                                      *)
  459. (*----------------------------------------------------------------------*)
  460.  
  461. BEGIN (* Async_Ring_Detect *)
  462.  
  463.    Async_Ring_Detect := ODD( Port[ UART_MSR + Async_Base ] SHR 6 );
  464.  
  465. END   (* Async_Ring_Detect *);
  466.  
  467. (*----------------------------------------------------------------------*)
  468. (*          Async_Send_Break --- Send break (attention) signal          *)
  469. (*----------------------------------------------------------------------*)
  470.  
  471. PROCEDURE Async_Send_Break;
  472.  
  473. (*----------------------------------------------------------------------*)
  474. (*                                                                      *)
  475. (*     Procedure:  Async_Send_Break                                     *)
  476. (*                                                                      *)
  477. (*     Purpose:    Sends break signal over communications port          *)
  478. (*                                                                      *)
  479. (*     Calling Sequence:                                                *)
  480. (*                                                                      *)
  481. (*        Async_Send_Break;                                             *)
  482. (*                                                                      *)
  483. (*     Calls:  None                                                     *)
  484. (*                                                                      *)
  485. (*----------------------------------------------------------------------*)
  486.  
  487. VAR
  488.    Old_Lcr   : BYTE;
  489.    Break_Lcr : BYTE;
  490.  
  491. BEGIN (* Async_Send_Break *)
  492.  
  493.    Old_Lcr   := Port[ UART_LCR + Async_Base ];
  494.    Break_Lcr := Old_Lcr;
  495.  
  496.    IF Break_Lcr >  127 THEN Break_Lcr := Break_Lcr - 128;
  497.    IF Break_Lcr <=  63 THEN Break_Lcr := Break_Lcr +  64;
  498.  
  499.    Port[ UART_LCR + Async_Base ] := Break_Lcr;
  500.  
  501.    DELAY( Async_Break_Length * 10 );
  502.  
  503.    Port[ UART_LCR + Async_Base ] := Old_Lcr;
  504.  
  505. END   (* Async_Send_Break *);
  506.  
  507. (*----------------------------------------------------------------------*)
  508. (*     Async_Send_String --- Send string over communications port       *)
  509. (*----------------------------------------------------------------------*)
  510.  
  511. PROCEDURE Async_Send_String( S : AnyStr );
  512.  
  513. (*----------------------------------------------------------------------*)
  514. (*                                                                      *)
  515. (*     Procedure:  Async_Send_String                                    *)
  516. (*                                                                      *)
  517. (*     Purpose:    Sends string out over communications port            *)
  518. (*                                                                      *)
  519. (*     Calling Sequence:                                                *)
  520. (*                                                                      *)
  521. (*        Async_Send_String( S : AnyStr );                              *)
  522. (*                                                                      *)
  523. (*           S --- String to send                                       *)
  524. (*                                                                      *)
  525. (*     Calls:  Async_Send                                               *)
  526. (*                                                                      *)
  527. (*----------------------------------------------------------------------*)
  528.  
  529. VAR
  530.    I : INTEGER;
  531.  
  532. BEGIN  (* Async_Send_String *)
  533.  
  534.   FOR I := 1 TO LENGTH( S ) DO
  535.      Async_Send( S[I] )
  536.  
  537. END    (* Async_Send_String *);
  538.  
  539. (*----------------------------------------------------------------------*)
  540. (*     Async_Send_String_With_Delays --- Send string with timed delays  *)
  541. (*----------------------------------------------------------------------*)
  542.  
  543. PROCEDURE Async_Send_String_With_Delays( S          : AnyStr;
  544.                                          Char_Delay : INTEGER;
  545.                                          EOS_Delay  : INTEGER  );
  546.  
  547. (*----------------------------------------------------------------------*)
  548. (*                                                                      *)
  549. (*     Procedure:  Async_Send_String_With_Delays                        *)
  550. (*                                                                      *)
  551. (*     Purpose:    Sends string out over communications port with       *)
  552. (*                 specified delays for each character and at the       *)
  553. (*                 end of the string.                                   *)
  554. (*                                                                      *)
  555. (*     Calling Sequence:                                                *)
  556. (*                                                                      *)
  557. (*        Async_Send_String_With_Delays( S          : AnyStr ;          *)
  558. (*                                       Char_Delay : INTEGER;          *)
  559. (*                                       EOS_Delay  : INTEGER );        *)
  560. (*                                                                      *)
  561. (*           S          --- String to send                              *)
  562. (*           Char_Delay --- Number of milliseconds to delay after       *)
  563. (*                          sending each character                      *)
  564. (*           EOS_Delay  --- Number of milleseconds to delay after       *)
  565. (*                          sending last character in string            *)
  566. (*                                                                      *)
  567. (*     Calls:  Async_Send                                               *)
  568. (*             Async_Send_String                                        *)
  569. (*             Length                                                   *)
  570. (*             Delay                                                    *)
  571. (*                                                                      *)
  572. (*     Remarks:                                                         *)
  573. (*                                                                      *)
  574. (*        This routine is useful when writing routines to perform       *)
  575. (*        non-protocol uploads.  Many computer systems require delays   *)
  576. (*        between receipt of characters for correct processing.  The    *)
  577. (*        delay for end-of-string usually applies when the string       *)
  578. (*        represents an entire line of a file.                          *)
  579. (*                                                                      *)
  580. (*        If delays are not required, Async_Send_String is faster.      *)
  581. (*        This routine will call Async_Send_String is no character      *)
  582. (*        delay is to be done.                                          *)
  583. (*                                                                      *)
  584. (*----------------------------------------------------------------------*)
  585.  
  586. VAR
  587.    I : INTEGER;
  588.  
  589. BEGIN  (* Async_Send_String_With_Delays *)
  590.  
  591.    IF Char_Delay <= 0 THEN
  592.       Async_Send_String( S )
  593.    ELSE
  594.       FOR I := 1 TO LENGTH( S ) DO
  595.          BEGIN
  596.             Async_Send( S[I] );
  597.             Delay( Char_Delay );
  598.          END;
  599.  
  600.    IF EOS_Delay > 0 THEN Delay( EOS_Delay );
  601.  
  602. END    (* Async_Send_String_With_Delays *);
  603.  
  604. (*----------------------------------------------------------------------*)
  605. (*      Async_Percentage_Used --- Report Percentage Buffer Filled       *)
  606. (*----------------------------------------------------------------------*)
  607.  
  608. FUNCTION Async_Percentage_Used : REAL;
  609.  
  610. (*----------------------------------------------------------------------*)
  611. (*                                                                      *)
  612. (*     Function:   Async_Percent_Used                                   *)
  613. (*                                                                      *)
  614. (*     Purpose:    Reports percentage of com buffer currently filled    *)
  615. (*                                                                      *)
  616. (*     Calling Sequence:                                                *)
  617. (*                                                                      *)
  618. (*        Percentage := Async_Percentage_Used : Real;                   *)
  619. (*                                                                      *)
  620. (*           Percentage gets how much of buffer is filled;              *)
  621. (*           value goes from 0.0 (empty) to 1.0 (totally full).         *)
  622. (*                                                                      *)
  623. (*     Calls:  None                                                     *)
  624. (*                                                                      *)
  625. (*     Remarks:                                                         *)
  626. (*                                                                      *)
  627. (*       This routine is helpful when incorporating handshaking into    *)
  628. (*       a communications program.  For example, assume that the host   *)
  629. (*       computer uses the XON/XOFF (DC1/DC3) protocol.  Then the       *)
  630. (*       PC program should issue an XOFF  to the host when the value    *)
  631. (*       returned by Async_Percentage_Used > .75 or so.  When the       *)
  632. (*       utilization percentage drops below .25 or so, the PC program   *)
  633. (*       should transmit an XON.                                        *)
  634. (*                                                                      *)
  635. (*----------------------------------------------------------------------*)
  636.  
  637. BEGIN (* Async_Percentage_Used *)
  638.  
  639.    Async_Percentage_Used := Async_Buffer_Used / ( Async_Buffer_Size + 1 );
  640.  
  641. END   (* Async_Percentage_Used *);
  642.  
  643. (*----------------------------------------------------------------------*)
  644. (*     Async_Purge_Buffer --- Purge communications input buffer         *)
  645. (*----------------------------------------------------------------------*)
  646.  
  647. PROCEDURE Async_Purge_Buffer;
  648.  
  649. (*----------------------------------------------------------------------*)
  650. (*                                                                      *)
  651. (*     Procedure:  Async_Purge_Buffer                                   *)
  652. (*                                                                      *)
  653. (*     Purpose:    Purges communications input buffer                   *)
  654. (*                                                                      *)
  655. (*     Calling Sequence:                                                *)
  656. (*                                                                      *)
  657. (*        Async_Purge_Buffer;                                           *)
  658. (*                                                                      *)
  659. (*     Calls:  Async_Receive                                            *)
  660. (*                                                                      *)
  661. (*----------------------------------------------------------------------*)
  662.  
  663. VAR
  664.    C: CHAR;
  665.    L: INTEGER;
  666.  
  667. BEGIN  (* Async_Purge_Buffer *)
  668.  
  669.    L     := 10000 DIV Async_Baud_Rate;
  670.  
  671.    IF L <= 0 THEN
  672.       L := 3;
  673.  
  674.    REPEAT
  675.       DELAY( L )
  676.    UNTIL ( NOT Async_Receive( C ) );
  677.  
  678. END    (* Async_Purge_Buffer *);
  679.  
  680. (*----------------------------------------------------------------------*)
  681. (*          Async_Peek --- Peek ahead in communications buffer          *)
  682. (*----------------------------------------------------------------------*)
  683.  
  684. FUNCTION Async_Peek( Nchars : INTEGER ) : CHAR;
  685.  
  686. (*----------------------------------------------------------------------*)
  687. (*                                                                      *)
  688. (*     Function:   Async_Peek                                           *)
  689. (*                                                                      *)
  690. (*     Purpose:    Peeks ahead in comm buffer                           *)
  691. (*                                                                      *)
  692. (*     Calling Sequence:                                                *)
  693. (*                                                                      *)
  694. (*        Ch := Async_Peek( NChars: INTEGER) : CHAR;                    *)
  695. (*                                                                      *)
  696. (*           NChars --- # of characters to peek ahead                   *)
  697. (*           Ch     --- returned (peeked) character                     *)
  698. (*                                                                      *)
  699. (*     Calls:  None                                                     *)
  700. (*                                                                      *)
  701. (*----------------------------------------------------------------------*)
  702.  
  703. VAR
  704.    I: INTEGER;
  705.  
  706. BEGIN (* Async_Peek *)
  707.  
  708.    I := ( Async_Buffer_Tail + NChars ) MOD Async_Buffer_Size;
  709.  
  710.    IF ( I > Async_Buffer_Head ) THEN
  711.       Async_Peek := CHR( 0 )
  712.    ELSE
  713.       Async_Peek := Async_Buffer_Ptr^[ I ];
  714.  
  715. END   (* Async_Peek *);
  716.  
  717. (*----------------------------------------------------------------------*)
  718. (*         Async_Setup_Port --- Setup port address and IRQ line         *)
  719. (*----------------------------------------------------------------------*)
  720.  
  721. PROCEDURE Async_Setup_Port( ComPort       : INTEGER;
  722.                             Base_Address  : INTEGER;
  723.                             IRQ_Line      : INTEGER;
  724.                             Int_Numb      : INTEGER );
  725.  
  726. (*----------------------------------------------------------------------*)
  727. (*                                                                      *)
  728. (*     Procedure:  Async_Setup_Port                                     *)
  729. (*                                                                      *)
  730. (*     Purpose:    Sets up port address and IRQ line                    *)
  731. (*                                                                      *)
  732. (*     Calling Sequence:                                                *)
  733. (*                                                                      *)
  734. (*        Async_Setup_Port( ComPort       : INTEGER;                    *)
  735. (*                          Base_Address  : INTEGER;                    *)
  736. (*                          IRQ_Line      : INTEGER;                    *)
  737. (*                          Int_Numb      : INTEGER );                  *)
  738. (*                                                                      *)
  739. (*           ComPort      --- which port (1 though MaxComPorts)         *)
  740. (*           Base_Address --- Base address of port.  If -1, then        *)
  741. (*                            standard default address used.            *)
  742. (*           IRQ_Line     --- IRQ line for interrupts for port.  If -1, *)
  743. (*                            then standard default irq line used.      *)
  744. (*           Int_Numb     --- Interrupt vector number for port.  If -1, *)
  745. (*                            then standard default interrupt # used.   *)
  746. (*                                                                      *)
  747. (*     Calls:  None                                                     *)
  748. (*                                                                      *)
  749. (*----------------------------------------------------------------------*)
  750.  
  751. VAR
  752.    Port_Offset : INTEGER;
  753.  
  754. BEGIN  (* Async_Setup_Port *)
  755.  
  756.    IF ( ( ComPort > 0 ) AND ( ComPort <= MaxComPorts ) ) THEN
  757.       BEGIN
  758.          IF ( Base_Address = -1 ) THEN
  759.             Base_Address := Default_Com_Base[ComPort];
  760.          IF ( IRQ_Line = -1 ) THEN
  761.             IRQ_Line := Default_Com_IRQ[ComPort];
  762.          IF ( Int_Numb = -1 ) THEN
  763.             Int_Numb := Default_Com_Int[ComPort];
  764.          Com_Base [ComPort]   := Base_Address;
  765.          Com_Irq  [ComPort]   := IRQ_Line;
  766.          Com_Int  [ComPort]   := Int_Numb;
  767.          Port_Offset          := RS232_Base + ( PRED( ComPort ) SHL 1 );
  768.          MemW[$0:Port_Offset] := Base_Address;
  769.       END;
  770.  
  771. END    (* Async_Setup_Port *);
  772.  
  773. (*----------------------------------------------------------------------*)
  774. (*         Async_Release_Buffers --- Release buffers for serial ports   *)
  775. (*----------------------------------------------------------------------*)
  776.  
  777. PROCEDURE Async_Release_Buffers;
  778.  
  779. (*----------------------------------------------------------------------*)
  780. (*                                                                      *)
  781. (*     Procedure:  Async_Release_Buffers;                               *)
  782. (*                                                                      *)
  783. (*     Purpose:    Releases send and receive buffers                    *)
  784. (*                                                                      *)
  785. (*     Calling Sequence:                                                *)
  786. (*                                                                      *)
  787. (*        Async_Release_Buffers;                                        *)
  788. (*                                                                      *)
  789. (*     Calls:  None                                                     *)
  790. (*                                                                      *)
  791. (*----------------------------------------------------------------------*)
  792.  
  793. BEGIN  (* Async_Release_Buffers *)
  794.  
  795.                              (* If port open, close it down first.  *)
  796.    IF Async_Open_Flag THEN
  797.       Async_Close( FALSE );
  798.  
  799.    FREEMEM( Async_Buffer_Ptr  , Async_Buffer_Size  + 1 );
  800.    FREEMEM( Async_OBuffer_Ptr , Async_OBuffer_Size + 1 );
  801.  
  802. END    (* Async_Release_Buffers *);
  803.  
  804. (*----------------------------------------------------------------------*)
  805. (*   Async_Flush_Output_Buffer --- Flush output buffer for serial port  *)
  806. (*----------------------------------------------------------------------*)
  807.  
  808. PROCEDURE Async_Flush_Output_Buffer;
  809.  
  810. (*----------------------------------------------------------------------*)
  811. (*                                                                      *)
  812. (*     Procedure:  Async_Flush_Output_Buffer;                           *)
  813. (*                                                                      *)
  814. (*     Purpose:    Flushes output buffer for serial port.               *)
  815. (*                                                                      *)
  816. (*     Calling Sequence:                                                *)
  817. (*                                                                      *)
  818. (*        Async_Flush_Output_Buffer;                                    *)
  819. (*                                                                      *)
  820. (*     Calls:  None                                                     *)
  821. (*                                                                      *)
  822. (*----------------------------------------------------------------------*)
  823.  
  824. BEGIN  (* Async_Flush_Output_Buffer *)
  825.  
  826.    Async_OBuffer_Head  := Async_OBuffer_Tail;
  827.    Async_OBuffer_Used  := 0;
  828.  
  829. END    (* Async_Flush_Output_Buffer *);
  830.  
  831. (*----------------------------------------------------------------------*)
  832. (*   Async_Drain_Output_Buffer --- Wait for output buffer to drain      *)
  833. (*----------------------------------------------------------------------*)
  834.  
  835. PROCEDURE Async_Drain_Output_Buffer( Max_Wait_Time : INTEGER );
  836.  
  837. (*----------------------------------------------------------------------*)
  838. (*                                                                      *)
  839. (*     Procedure:  Async_Drain_Output_Buffer;                           *)
  840. (*                                                                      *)
  841. (*     Purpose:    Waits for output buffer to drain.                    *)
  842. (*                                                                      *)
  843. (*     Calling Sequence:                                                *)
  844. (*                                                                      *)
  845. (*        Async_Drain_Output_Buffer( Max_Wait_Time : INTEGER );         *)
  846. (*                                                                      *)
  847. (*           Max_Wait_Time --- Maximum # of seconds to wait for         *)
  848. (*                             output buffer to drain.                  *)
  849. (*                                                                      *)
  850. (*     Calls:  TimeOfDay                                                *)
  851. (*             TimeDiff                                                 *)
  852. (*             GiveUpTime                                               *)
  853. (*                                                                      *)
  854. (*----------------------------------------------------------------------*)
  855.  
  856. VAR
  857.    T1 : LONGINT;
  858.  
  859. BEGIN  (* Async_Drain_Output_Buffer *)
  860.  
  861.    T1 := TimeOfDay;
  862.  
  863.    WHILE( ( Async_OBuffer_Head <> Async_OBuffer_Tail    ) AND
  864.           ( TimeDiff( T1 , TimeOfDay ) <= Max_Wait_Time )     ) DO
  865. {$IFDEF MTASK}
  866.       GiveUpTime( 1 );
  867. {$ELSE}
  868.       ;
  869. {$ENDIF}
  870.  
  871. END    (* Async_Drain_Output_Buffer *);
  872.  
  873. (*----------------------------------------------------------------------*)
  874. (*   Async_Port_Address_Given --- Check if port address in memory       *)
  875. (*----------------------------------------------------------------------*)
  876.  
  877. FUNCTION Async_Port_Address_Given( Com_Port : INTEGER ) : BOOLEAN;
  878.  
  879. (*----------------------------------------------------------------------*)
  880. (*                                                                      *)
  881. (*     Procedure:  Async_Port_Address_Given;                            *)
  882. (*                                                                      *)
  883. (*     Purpose:    Checks if port address in memory.                    *)
  884. (*                                                                      *)
  885. (*     Calling Sequence:                                                *)
  886. (*                                                                      *)
  887. (*        There := Async_Port_Address_Given( Com_Port : INTEGER ) :     *)
  888. (*                                         BOOLEAN;                     *)
  889. (*                                                                      *)
  890. (*           Com_Port --- Port to check (1 through MaxComPorts)         *)
  891. (*           There    --- TRUE if port address in memory.               *)
  892. (*                                                                      *)
  893. (*----------------------------------------------------------------------*)
  894.  
  895. VAR
  896.    Port_Offset : INTEGER;
  897.  
  898. BEGIN  (* Async_Port_Address_Given *)
  899.  
  900.    IF ( ( Com_Port > 0 ) AND ( Com_Port < MaxComPorts ) ) THEN
  901.       BEGIN
  902.          Port_Offset              := RS232_Base + ( PRED( Com_Port ) SHL 1 );
  903.          Async_Port_Address_Given := ( MemW[$0:Port_Offset] <> 0 );
  904.       END
  905.    ELSE
  906.       Async_Port_Address_Given := FALSE;
  907.  
  908. END    (* Async_Port_Address_Given *);
  909.